/**
 * Player.java
 */
package edu.gatech.startrader.player;

import java.util.ArrayList;
import java.util.List;

import edu.gatech.startrader.ship.Ship;
import edu.gatech.startrader.trade.TradeGood;
import edu.gatech.startrader.universe.Planet;
import edu.gatech.startrader.universe.Universe;

/**
 * Player Class
 * This class creates the player and controls all aspects of the player
 * @author Team Bamf (Team 30)
 * @version 1.0
 */
public class Player {
	/**
	 * name of the player
	 */
	private final String name;
	
	/**
	 * number of credits the player has
	 */
	private int credits;
	
	/**
	 * the ship the player owns
	 */
	private Ship ship;
	
	/**
	 * list of mercenaries
	 */
	private List<Mercenary> mercenaries;
	
	/**
	 * the skills that the player has
	 */
	private Skills skills;
	
	/**
	 * Player Constructor
	 * This constructor creates a new player
	 * @param playerName sets player name
	 * @param playerSkills sets player skills
	 * @param playerCredits sets player credits
	 * @param playerShip sets player ship
	 */
	public Player(String playerName, Skills playerSkills, int playerCredits, Ship playerShip){
		name = playerName;
		skills = playerSkills;
		credits = playerCredits;
		ship = playerShip;
		mercenaries = new ArrayList<Mercenary>();
	}
	
	/**
	 * warp Method
	 * This method warps the player from one planet to another
	 * @param start the planet the player starts from
	 * @param end the planet that the player is going to
	 */
	public void warp(Planet start, Planet end) {
		ship.useFuel(Universe.calculateFuelCost(start, end));
	}
	
	/**
	 * addCargo method
	 * This method adds cargo to the ship
	 * @param type the category the item belongs to
	 * @param amount the amount of the item added
	 */
	public void addCargo(TradeGood type, int amount) {
		ship.fillCargo(type, amount);
	}
	
	/**
	 * removeCargo method
	 * This method removes cargo from the ship
	 * @param type the category the item belongs to
	 * @param amount the amount of the item subtracted
	 */
	public void removeCargo(TradeGood type, int amount) {
		ship.emptyCargo(type, amount);
	}
	
	/**
	 * toString method
	 * Prints out player-related information
	 * @return the object as a String
	 */
	public String toString() {
		return "Player: \n" +
				"Name: " + name + "\n" +
				"Credits: " + credits + "\n" +
				"Skills: " + skills  + "\n" +
				"Ship: " + ship + "\n";
	}
	
	/**
	 * getName method
	 * This method gets the player's name
	 * @return name
	 */
	public String getName() {
		return name;
	}
	
	/**
	 * getCredits method
	 * This method gets the number of credits the player has
	 * @return credits player has
	 */
	public int getCredits() {
		return credits;
	}
	
	/**
	 * remainingCargoSpace method
	 * This method gets the remaining space left in the cargo
	 * @return space left in cargo
	 */
	public int remainingCargoSpace() {
		return ship.remainingCargoSpace();
	}
	
	/**
	 * pay Method
	 * This method is used to spend credits to buy something. 
	 * It is called when the amount of credits need to be reduced
	 * @param amount how many credits will be reduced from the player account
	 */
	public void pay(int amount) {
		if(amount > credits) {
			throw new IllegalArgumentException(
					"Cannot pay more money than the player has");
		}
		credits -= amount;
	}

	/**
	 * receive Method
	 * This method adds credits to the player's total amount of credits
	 * @param amount of credits 
	 */
	public void recieve(int amount) {
		credits += amount;
	}

	/**
	 * getShip method
	 * This method returns the player's ship.
	 * @return ship
	 */
	public Ship getShip() {
		return ship;
	}
	
	/**
	 * setShip method
	 * This method sets the player's ship
	 * @param s the ship 
	 */
	public void setShip(Ship s) {
		ship = s;
	}
	
	/**
	 * getSkills method
	 * This method gets the player's skills
	 * will account for the skills of mercenaries
	 * @return skills
	 */
	public Skills getSkills() {
		int maxPilot = skills.getPilot(), 
				maxEngineer = skills.getEngineer(), 
				maxTrader = skills.getTrader(),
				maxFighter = skills.getFighter();
		for(int i = 0; i < mercenaries.size(); i++) {
			Skills mercenarySkills = mercenaries.get(i).getSkills();
			if(mercenarySkills.getPilot() > maxPilot) {
				maxPilot = mercenarySkills.getPilot();
			}
			if(mercenarySkills.getEngineer() > maxEngineer) {
				maxEngineer =  mercenarySkills.getEngineer();
			}
			if(mercenarySkills.getTrader() > maxTrader) {
				maxTrader = mercenarySkills.getTrader(); 
			}
			if(mercenarySkills.getFighter() > maxFighter){
				maxFighter = mercenarySkills.getFighter();
			}
		}
		return new Skills(maxPilot, maxFighter, maxEngineer, maxTrader);
	}
	
	/**
	 * setSkills method
	 * This method sets the player's skills
	 * @param s the skill
	 */
	public void setSkills(Skills s) {
		skills = s;
	}
	
	/**
	 * hireMercenary method
	 * This method adds a new mercenary to the player's crew.
	 * @param m the Mercenary to be hired.
	 */
	public void hireMercenary(Mercenary m) {
		mercenaries.add(m);
	}
	
	/**
	 * fireMercenary method
	 * This method allows you to get rid of a mercenary.
	 * @param m the Mercenary that is to be removed 
	 */
	public void fireMercenary(Mercenary m) {
		mercenaries.remove(m);
	}
	
	/**
	 * getCargoItems method
	 * Collects the number of cargo holds holding the specific resource
	 * @param resource the resource we are checking for
	 * @return the number of cargo hold holding that resource
	 */
	public int getCargoItems(TradeGood resource) {
		return ship.getCargoItems(resource);
	}
	
	/**
	 * payMercenaries method
	 * This method is used to pay all of the Mercenaries. 
	 */
	public void payMercenaries() {
		boolean firedMercenaries = false;
		for(int i = 0; i < mercenaries.size(); i++) {
			try {
				pay(mercenaries.get(i).getPrice());
			} catch(IllegalArgumentException iae) { // $codepro.audit.disable logExceptions
				fireMercenary(mercenaries.get(i));
				firedMercenaries = true;
			}
		}
		if(firedMercenaries) {
			throw new IllegalArgumentException(
					"You could not pay some of your crew, so they left.");
		}
	}
}
